package controllers

import akka.actor.ActorSystem
import javax.inject._
import play.api.Logging
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import play.api.libs.json._
import services.kingdee.{AuthUser, CookieDict, KindeeAuthService, ReceiveService}

import scala.concurrent.{ExecutionContext, Future}

case class Parameters(parameters: String)

@Singleton
class KingdeeWebApi @Inject()(
                               cc: ControllerComponents,
                               actorSystem: ActorSystem,
                               kvSrv: KindeeAuthService,
                               ks: ReceiveService
                             )(implicit exec: ExecutionContext)
  extends AbstractController(cc)
    with Logging {
  val errorInfo = (x: String) =>
    s"""response_error:Code(-2147467259);{
       |"Message":"$x","MessageCode":"002005030013414","LoginResultType":0,
       |"AccessToken":null,"KdAccessResult":null,"IsSuccessByAPI":false}""".stripMargin

  def index = Action {
    Ok(errorInfo("")) //.as("text/html;charset=gb18030")
  }

  def show(page: String) = Action { implicit request =>
    logger.debug(page)
    //    kdPost.view("BD_MATERIAL", Json.obj("Number"-> "A01LC01016D01"))
    val res = ks.test(page)
    Ok(res.toString)
  }

  val parameters = Form(
    mapping(
      "parameters" -> nonEmptyText
    )(Parameters.apply)(Parameters.unapply)
  )

  // 标记未来删除
  def webApi_d(apiUrl: String) = Action.async { implicit request =>
    logger.info(s"webApi:$apiUrl")
    val thisCookies = request.cookies
    val isValidateUser = kvSrv.validateUser(
      CookieDict(
        aspSession = thisCookies
          .get("ASP.NET_SessionId")
          .getOrElse(
            Cookie("ASP.NET_SessionId", "00000000001")
          ).value,
        kdSessionid = thisCookies
          .get("kdservice-sessionid")
          .getOrElse(
            Cookie("kdservice-sessionid", "000000000001")
          ).value)
    ).acctID.equals("")
    val dataModel: JsValue = request.contentType.getOrElse("") match {
      case "application/json" => request.body.asJson.get("parameters")
      case _ => {
        parameters.bindFromRequest().fold(
          formWithErrors => {
            //println("is application/badform")
            BadRequest(formWithErrors.toString)
            Json.arr("")
          },
          formWithData => {
            //println("is application/form")
            implicit val formDataWrite = Json.writes[Parameters]
            Json.parse(formWithData.parameters)
          }
        )
      }
    }
    logger.debug(dataModel.toString())
    if (apiUrl.equals("Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc")) {
      val authUser: AuthUser = AuthUser(
        acctID = dataModel(0).as[String],
        userName = dataModel(1).as[String],
        password = dataModel(2).as[String]
      )
      //println(authUser)
      val code = kvSrv.loginAuth(authUser)
      Future(Ok(code.messages)
        .withCookies(Cookie(name = "ASP.NET_SessionId", value = code.aspSession, httpOnly = false))
        .withCookies(Cookie(name = "kdservice-sessionid", value = code.kdSessionid, httpOnly = false))
      )
    }
    else if (dataModel.head.toString.equals("") || isValidateUser) {
      Future(Ok(errorInfo("")))
    }
    else {
      val response: Future[String] = apiUrl match {
//        case "Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc" => ks.webapiValidateUser(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.View.common.kdsvc" => ks.webapiView(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc" => ks.webapiSave(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave.common.kdsvc" => ks.webapiBatchSave(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit.common.kdsvc" => ks.webapiSubmit(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc" => ks.webapiAudit(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit.common.kdsvc" => ks.webapiUnAudit(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete.common.kdsvc" => ks.webapiDelete(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc" => ks.webapiQuery(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.StatusConvert.common.kdsvc" => ks.webapiStatusConvert(dataModel)
        case "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExcuteOperation.common.kdsvc" => ks.webapiExcuteOperation(dataModel)
        case "Kingdee.K3.SCM.WebApi.ServicesStub.OutStockService.Save.common.kdsvc" => ks.webapiOutStockService(dataModel)
        case "Kingdee.K3.SCM.WebApi.ServicesStub.ReturnStockService.Save.common.kdsvc" => ks.webapiReturnStockService(dataModel)
        case "Kingdee.K3.SCM.WebApi.ServicesStub.InstockService.Save.common.kdsvc" => ks.webapiInstockService(dataModel)
        case "Kingdee.K3.SCM.WebApi.ServicesStub.PurReturnService.Save.common.kdsvc" => ks.webapiPurReturnService(dataModel)
        case _ => ks.webapiOther(apiUrl, dataModel)
      }
      response.map(res =>
        Ok(res)
          .withCookies(thisCookies.head)
          .withCookies(thisCookies.last)
      )
    }
  }

  def webApi(apiUrl: String) = Action.async { implicit request =>
    logger.debug(s"webApi:$apiUrl")
    val dataModel: JsValue = request.body match {
      case a: AnyContentAsJson => {
        logger.debug(s"body is AnyContentAsJson:\n${a.asJson.get.toString()}")
        a.asJson.get
      }
      case a: AnyContentAsRaw => {
        logger.debug(s"body is AnyContentAsRaw:\n${a.asRaw.get.asBytes().get.decodeString("UTF8")}")
        Json.parse(a.asRaw.get.asBytes().get.decodeString("UTF8"))
      }
      case a: AnyContentAsText => {
        logger.debug(s"body is AnyContentAsText\n${a.asText}")
        Json.parse(a.asText.get)
      }
      //case a:  AnyContentAsXml => println(s"request.body.getClass is play.api.mvc.AnyContentAsXml\n${a.asXml.get.toString()}")
      case a: AnyContentAsFormUrlEncoded => {
        logger.debug("body is AnyContentAsFormUrlEncoded")
        val d = a.asFormUrlEncoded.get
        val deb = d("parameters")
        logger.debug(deb(0).toString)
        logger.debug(deb(0).getClass.toString)
        Json.obj("parameters" -> Json.parse(deb(0)))
      }
      //case a:  AnyContentAsMultipartFormData => println("request.body.getClass is play.api.mvc.AnyContentAsMultipartFormData")
      case a: AnyContentAsMultipartFormData => {
        logger.debug(s"body is ${request.body.getClass},contentType: ${request.contentType}")
        Json.obj("parameters" ->
          parameters.bindFromRequest().fold(
            formWithErrors => {
              //println("is application/badform")
              BadRequest(formWithErrors.toString)
              Json.arr("")
            },
            formWithData => {
              //println("is application/form")
              implicit val formDataWrite = Json.writes[Parameters]
              Json.parse(formWithData.parameters)
            }
          )
        )
      }
      case _ => {
        println(s"body is ${request.body.getClass},contentType: ${request.contentType}")
        Json.obj("parameters" -> Json.arr(""))
      }
    }
    if (apiUrl.equals("Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc")) {
      val authUser: AuthUser = AuthUser(
        acctID = (dataModel \ "parameters") (0).as[String],
        userName = (dataModel \ "parameters") (1).as[String],
        password = (dataModel \ "parameters") (2).as[String]
      )
      //println(authUser)
      val code = kvSrv.loginAuth(authUser)
      Future(Ok(code.messages)
        .withCookies(Cookie(name = "ASP.NET_SessionId", value = code.aspSession, httpOnly = false))
        .withCookies(Cookie(name = "kdservice-sessionid", value = code.kdSessionid, httpOnly = false))
      )
    } else {
      val thisCookies = request.cookies
      val headers = request.headers.headers
      val version = headers.filter(f => f._1 == "X-Api-Auth-Version")
      logger.debug("X-Api-Auth-Version =>" + version.toString())
      val isValidateUser = if (version.isEmpty) {
        kvSrv.validateUser(
          CookieDict(
            aspSession = thisCookies
              .get("ASP.NET_SessionId")
              .getOrElse(
                Cookie("ASP.NET_SessionId", "00000000001")
              ).value,
            kdSessionid = thisCookies
              .get("kdservice-sessionid")
              .getOrElse(
                Cookie("kdservice-sessionid", "000000000001")
              ).value)
        )
      } else {
        kvSrv.validateUser2(apiUrl, headers)
      }
      logger.debug(dataModel.toString())
      //      if (dataModel.head.toString.equals("") || !isValidateUser) {
      if (isValidateUser.acctID.equals("")) {
        Future(Ok(errorInfo("not isValidateUser")))
      }
      else {
        logger.info(s"webApi ${isValidateUser.acctID} $apiUrl ${dataModel.toString}")
        ks.setDCId(isValidateUser.acctID)
        val response = ks.apiMatch(apiUrl, dataModel)
        response.map(res =>
          Ok(res)
          //            .withCookies(thisCookies.head)
          //            .withCookies(thisCookies.last)
        )
      }
    }
  }
}